package demo1;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectClassdemo {
    public static void reflectNewInstance(){
        //创建对象
        Class<?> stu1;
        try {
            stu1=Class.forName("demo1.Student");
            Student student=(Student) stu1.newInstance();//可以拿到一个对象，返回值是Object,需要进行强制转换
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    // 反射私有的构造⽅法 屏蔽内容为获得公有的构造⽅法
    public static void reflectPrivateConstructor(){
        Class<?> stu1;
        try {
            stu1=Class.forName("demo1.Student");
            Constructor<?> constructor=stu1.getDeclaredConstructor(String.class,int.class);

            constructor.setAccessible(true);//设置为同意才可以访问

            Student student=(Student) constructor.newInstance("zhangsan",99);
            //此时就可以通过这个反射方式进行访问类中的私有方法，此方法就属于违背了封装属性中的私有方法不可再外部类中访问的原理


            //但此时运行的时候会报错，因为JVM本身还有一个保护机制，直接访问将会报错。
            // 得需要用户进行确认才可以，见29行代码所示
            System.out.println(student);


        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    // 反射私有属性
    public static void reflectPrivateField(){
        Class<?> stu1;
        try {
            stu1=Class.forName("demo1.Student");

            Field field = stu1.getDeclaredField("name");

            field.setAccessible(true);

            Student student=(Student)stu1.newInstance();
            //修改：set(修改的对象，"修改的值")
            field.set(student,"lisi");//原本的"zhangsan"修改为->"lisi"

            System.out.println(student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    

// 反射私有⽅法
public static void reflectPrivateMethod(){
    Class<?> stu1;
    try {
        stu1=Class.forName("demo1.Student");

        Method method=stu1.getDeclaredMethod("function",String.class);//参数，参数类型

        Student student=(Student)stu1.newInstance();

        method.setAccessible(true);
        //调用
        method.invoke(student,"我传一个参数");
        System.out.println(student);
    } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
    } catch (InstantiationException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
    }
}
    public static void main(String[] args) {
        //以下的反射机制的前提都是得有一个Class对象，如代码中:Class stu1;
        //reflectNewInstance();
        //reflectPrivateConstructor();
        //reflectPrivateField();
        ReflectClassdemo.reflectPrivateMethod();
    }
}
